package service

import (
	"errors"
	"gdmin/db"
	"gdmin/global"
	"gdmin/model"
	"gdmin/servlet"
	"gorm.io/gorm"
	"strconv"
)

type DictService struct {
}

func (s *DictService) QueryDictById(id int) *servlet.DictResp {
	var res servlet.DictResp
	global.DB.First(&res, id).Find(&res)
	if res.Id > 0 {
		if res.Pid > 0 {
			res.ParentName = s.findDictName(res.Pid)
		}
	}
	return &res
}
func (s *DictService) findDictName(id int) string {
	var res servlet.DictResp
	global.DB.First(&res, id).Find(&res)
	return res.Name
}

func (s *DictService) QueryDictItemById(id int) *servlet.DictItemResp {
	var res servlet.DictItemResp
	global.DB.First(&res, id).Find(&res)
	return &res
}

func (s *DictService) UpdateDictItem(req *servlet.UpdateDictItemReq) (*model.DictItem, error) {
	if req.Id == 0 {
		return nil, errors.New("修改时id必填")

	}

	if req.Name == "" {
		return nil, errors.New("字典项名称必填")
	}
	if req.Code == "" {
		return nil, errors.New("字典项编码必填")
	}

	if req.DictId < 0 {
		return nil, errors.New("字典id必填")
	}

	var old model.DictItem
	err := global.DB.First(&old, req.Id).Error
	if err != nil {
		return nil, err
	} else {

		err = checkDictItemNameRequire(req.Name, req.Id, req.DictId)
		if err != nil {
			return nil, err
		}
		err = checkDictItemCodeRequire(req.Code, req.Id, req.DictId)
		if err != nil {
			return nil, err
		}

		old.Name = req.Name
		old.Code = req.Code
		old.DictId = req.DictId

		err = global.DB.Transaction(func(tx *gorm.DB) error {
			return tx.Save(&old).Error
		})
		if err != nil {
			return nil, err
		} else {

			return &old, nil

		}

	}

}

func checkDictItemCodeRequire(code string, id int, dictId int) error {
	dictItem := model.DictItem{}
	err := global.DB.Where("code =?", code).Where("dict_id = ?", dictId).First(&dictItem).Error
	if err == nil {
		if dictItem.Id == 0 {
			return nil
		}
		if dictItem.Id != id && dictItem.DictId == dictId {
			return errors.New("字典下已有相同字典项编码")
		}
	} else {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil
		}
	}

	return err
}

func checkDictItemNameRequire(name string, id int, dictId int) error {
	dictItem := model.DictItem{}
	err := global.DB.Where("name =?", name).Where("dict_id = ?", dictId).First(&dictItem).Error
	if err == nil {
		if dictItem.Id == 0 {
			return nil
		}
		if dictItem.Id != id && dictItem.DictId == dictId {
			return errors.New("字典下已有相同字典项编码")
		}
	} else {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil
		}
	}

	return err
}

func (s *DictService) CreateDictItem(req *servlet.CreateDictItemReq) (*model.DictItem, error) {

	if req.Name == "" {
		return nil, errors.New("字典项名称必填")
	}
	if req.Code == "" {
		return nil, errors.New("字典项编码必填")
	}

	if req.DictId < 0 {
		return nil, errors.New("字典id必填")
	}

	err := checkDictItemNameRequire(req.Name, -1, req.DictId)
	if err != nil {
		return nil, err
	}

	err = checkDictItemCodeRequire(req.Code, -1, req.DictId)
	if err != nil {
		return nil, err
	}

	if err != nil {
		return nil, err
	} else {
		err = checkDictItemNameRequire(req.Name, -1, req.DictId)
		if err != nil {
			return nil, err
		}
		err = checkDictItemCodeRequire(req.Code, -1, req.DictId)
		if err != nil {
			return nil, err
		}

		var dictItem model.DictItem
		dictItem.Name = req.Name
		dictItem.Code = req.Code
		dictItem.DictId = req.DictId

		err = global.DB.Transaction(func(tx *gorm.DB) error {
			return tx.Create(&dictItem).Error
		})
		if err != nil {
			return nil, err
		} else {
			return &dictItem, nil
		}
	}
}

func (s *DictService) UpdateDict(req *servlet.UpdateDictReq) (*model.Dict, error) {
	if req.Id == 0 {
		return nil, errors.New("修改时id必填")

	}

	if req.Name == "" {
		return nil, errors.New("字典名称必填")
	}
	if req.Code == "" {
		return nil, errors.New("字典编码必填")
	}

	if req.Type < 0 {
		return nil, errors.New("字典类型必填")
	}

	var old model.Dict
	err := global.DB.First(&old, req.Id).Error
	if err != nil {
		return nil, err
	} else {

		err = checkDictNameRequire(req.Name, req.Id)
		if err != nil {
			return nil, err
		}
		err = checkDictCodeRequire(req.Code, req.Id)
		if err != nil {
			return nil, err
		}

		old.Name = req.Name
		old.Code = req.Code
		old.Type = req.Type
		old.Pid = req.Pid

		err = global.DB.Transaction(func(tx *gorm.DB) error {
			return tx.Save(&old).Error
		})
		if err != nil {
			return nil, err
		} else {

			return &old, nil

		}

	}
}

func (s *DictService) CreateDict(req *servlet.CreateDictReq) (*model.Dict, error) {
	if req.Name == "" {
		return nil, errors.New("字典称必填")
	}
	if req.Code == "" {
		return nil, errors.New("字典编码必填")
	}
	if req.Type < 0 {
		return nil, errors.New("字典类型必填")
	}
	err := checkDictNameRequire(req.Name, -1)
	if err != nil {
		return nil, err
	}
	err = checkDictCodeRequire(req.Code, -1)
	if err != nil {
		return nil, err
	}

	if err != nil {
		return nil, err
	} else {
		var dict model.Dict
		dict.Name = req.Name
		dict.Code = req.Code
		dict.Type = req.Type
		dict.Pid = req.Pid

		err = global.DB.Transaction(func(tx *gorm.DB) error {
			return tx.Create(&dict).Error
		})
		if err != nil {
			return nil, err
		} else {
			return &dict, nil
		}
	}
}

func checkDictCodeRequire(code string, id int) error {
	dict := model.Dict{}
	err := global.DB.Where("code =?", code).First(&dict).Error
	if err == nil {
		if dict.Id == 0 {
			return nil
		}
		if dict.Id != id {
			return errors.New("字典编码已存在")
		}
	} else {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil
		}
	}

	return err
}

func checkDictNameRequire(name string, id int) error {
	dict := model.Dict{}
	err := global.DB.Where("name =?", name).First(&dict).Error
	if err == nil {
		if dict.Id == 0 {
			return nil
		}
		if dict.Id != id {
			return errors.New("字典名称已存在")
		}
	} else {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil
		}
	}

	return err
}

func (s *DictService) PageDict(req *servlet.QueryDictReq) (*servlet.Pagination, error) {
	var d []*servlet.DictResp

	query := global.DB.Model(&d)
	if req.Name != "" {
		query.Where("name like ? ", "%"+req.Name+"%")
	}
	if req.Code != "" {
		query.Where("code like ? ", "%"+req.Code+"%")
	}
	if req.Type > 0 {
		query.Where("type = ? ", req.Type)
	}
	if req.Pid > 0 {
		query.Where("pid =? ", req.Pid)
	}

	page := db.CommonPage(&req.Pagination, &d, query)
	for _, item := range d {
		item.ParentName = s.findDictName(item.Pid)

	}
	return page, nil
}

func (s *DictService) ListDict() interface{} {
	dict := []model.Dict{}
	err := global.DB.Model(&dict).Error
	if err != nil {
		print(err)
	}
	return dict

}

func (s *DictService) TreeDict(param string) ([]model.NodeWithChildren, error) {
	if param != "" {

		atoi, err := strconv.Atoi(param)
		if err != nil {
			return nil, err
		}

		return s.dictTree(atoi), nil
	} else {
		return s.dictTree(-1), nil
	}
}

func (s *DictService) dictTree(pid int) []model.NodeWithChildren {

	var mts []model.Dict
	if pid > 0 {
		global.DB.Where("pid =?", pid).Find(&mts)
	} else {
		err := global.DB.Model(&model.Dict{}).Find(&mts).Error
		if err != nil {
			panic(err)
		}
	}

	dict := model.Dict{}
	tree := dict.MakeTree(mts)

	return tree
}

func (s *DictService) DeleteByDictId(param string) {
	global.DB.Where("id =?", param).Delete(&model.Dict{})
	return
}

func (s *DictService) PageDictItem(req servlet.QueryDictItemReq) (*servlet.Pagination, error) {
	if req.DictId < 0 {
		return nil, errors.New("字典id必传")

	}

	var d []*servlet.DictItemResp

	query := global.DB.Model(&model.DictItem{})

	if req.DictId > 0 {

		query.Where("dict_id = ? ", req.DictId)
	}
	if req.Name != "" {
		query.Where("name like ?", "%"+req.Name+"%")

	}

	page := db.CommonPage(&req.Pagination, &d, query)
	for _, item := range d {
		item.DictName = s.findDictName(item.DictId)

	}
	return page, nil
}
